﻿local SceneManager = {
    ---@type SceneInfo[]
    scene_info = {},
    ---@type role_info []
    role_info = {}
}

---@class SceneInfo
local scene_info = {
    scene_id= {},
    name = "",
    roles = {}
}

---@class role_info
local role_info = {
    prx = {},
    ---@type role []
    role = {}
}

---@class role
local role = {
    ---@type pos {}
    pos = {},
    role_uid = 0,
    scene_id = 0
}

---@class pos
local pos = {
    x = 0,
    y = 0,
    z = 0,
}

function SceneManager:AddScene(scene_id, name)
    SceneManager.scene_info[scene_id] = SceneManager.scene_info[scene_id] or {}
    SceneManager.scene_info[scene_id].scene_id = scene_id
    SceneManager.scene_info[scene_id].name = name
end


function SceneManager:SyncSceneRoleData(role_uid, scene_id, pos, is_enter_scene)
    if is_enter_scene then
        local prx = SceneManager.role_info[role_uid].prx
        if prx == nil then
            ctx:log_debug("prx is nil , role id "..role_uid)
            return
        end
        for key, value in pairs(SceneManager.role_info) do
            if value.role.scene_id == scene_id then
                if value.role.role_uid ~= role_uid then
                    value.prx:EnterScene(1, role_uid, scene_id, pos)
                    prx:EnterScene(1, value.role.role_uid, scene_id, value.role.pos)
                end
            end
        end
    else
        local sync_data = {
            role_info = {}
        }
        sync_data.role_info[1] = SceneManager.role_info[role_uid].role
        --print_r(sync_data)
        --print(type(sync_data.role_info))
        for key, value in pairs(SceneManager.role_info) do
            if value.role.scene_id == scene_id then
                if value.role.role_uid ~=role_uid then
                    value.prx:SyncRoleData(sync_data)
                end
            end
        end
    end
end

function SceneManager:AddRole(role_uid, scene_id, pos, prx)
    if SceneManager.scene_info[scene_id] == nil then
        ctx:log_debug("scene is not exist")
        return false
    end
    SceneManager.role_info[role_uid] = SceneManager.role_info[role_uid] or {}
    SceneManager.role_info[role_uid].prx =  prx
    SceneManager.role_info[role_uid].role = {}
    SceneManager.role_info[role_uid].role.pos = {}
    SceneManager.role_info[role_uid].role.pos = pos
    SceneManager.role_info[role_uid].role.role_uid = role_uid
    SceneManager.role_info[role_uid].role.scene_id = scene_id
    return true
end


function SceneManager:RoleMove(role_uid, pos, prx)
    if SceneManager.role_info[role_uid] == nil then
        return false
    end
    SceneManager.role_info[role_uid] = SceneManager.role_info[role_uid] or {}
    SceneManager.role_info[role_uid].prx = prx
    SceneManager.role_info[role_uid].role = SceneManager.role_info[role_uid].role or {}
    SceneManager.role_info[role_uid].role.pos = pos
    return true
end

function SceneManager:CheckMove(role_uid, pos)
    if SceneManager.role_info[role_uid] == nil then
        return false
    end
    if math.abs(SceneManager.role_info[role_uid].role.pos.x - pos.x) <= 0.1 and
        math.abs(SceneManager.role_info[role_uid].role.pos.y - pos.y) <= 0.1 and
        math.abs(SceneManager.role_info[role_uid].role.pos.z - pos.z) <= 0.1 then
        return false
    end
    return true
end

function SceneManager:GetRoleSceneId(role_uid)
    if SceneManager.role_info[role_uid] == nil then
        return -1
    end
    return SceneManager.role_info[role_uid].role.scene_id
end

function on_tick(now)
end

function on_after_fork()    
    ctx:log_debug("on after fork")
    SceneManager:AddScene(1, "test1")
    SceneManager:AddScene(2, "test2")
    return true
end

function on_before_destroy()
end

StubScene={}

function StubScene:EnterScene(arg1,arg2,arg3)
    ctx:log_debug("Enter Scene")

    local proxy = {}
    if SceneManager.role_info~=nil and SceneManager.role_info[arg1] ~= nil and SceneManager.role_info[arg1].prx ~= nil then
        proxy = SceneManager.role_info[arg1].prx
    else
        proxy = Proxy:get_Synchronize_from_peer()
    end

    if proxy == nil then
        ctx:log_debug("get proxy faild")
        return
    end
    
    if SceneManager:AddRole(arg1, arg2, arg3, proxy) == false then
        proxy:EnterScene(2, arg1, arg2, arg3);
        return
    end

    SceneManager:SyncSceneRoleData(arg1,arg2,arg3,true)
end

function StubScene:Move(arg1,arg2)
    ctx:log_debug("Move ")

    local proxy = {}
    if SceneManager.role_info~=nil and SceneManager.role_info[arg1] ~= nil and SceneManager.role_info[arg1].prx ~= nil then
        proxy = SceneManager.role_info[arg1].prx
    else
        proxy = Proxy:get_Synchronize_from_peer()
    end
    
    if proxy == nil then
        ctx:log_debug("get proxy faild")
        return
    end

    if SceneManager:CheckMove(arg1, arg2) == false then
        return
    end

    if SceneManager:RoleMove(arg1, arg2, proxy) == false then
        proxy:Move(4, arg1, arg2);
        return
    end

    proxy:Move(1, arg1, arg2);

    SceneManager:SyncSceneRoleData(arg1, SceneManager:GetRoleSceneId(arg1), nil, false)

end

